#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "MemcacheClient.cpp"

using namespace std;

extern "C"  
{  
    #include "lua.h"  
    #include "lauxlib.h"  
    #include "lualib.h"  
}  

#if defined(_WIN32) || defined(_WIN64)
#define _DLLExport _declspec(dllexport)
#else
#define _DLLExport 
#endif

static int lua_create_libmemcahed_client(lua_State* L)
{
    CMemcacheClient** p = (CMemcacheClient**)lua_newuserdata(L, sizeof(CMemcacheClient));
    *p = new CMemcacheClient;
    luaL_getmetatable(L, "libmemcahed_client");
    lua_setmetatable(L, -2);

    return 1;
}

static int lua_init_libmemcahed_client(lua_State* L)
{
    CMemcacheClient** p = (CMemcacheClient**)luaL_checkudata(L, 1, "libmemcahed_client");
    luaL_argcheck(L, p != NULL, 1, "invalid user data");

    const char* host = luaL_checkstring(L, 2);
    int port = luaL_checkinteger(L, 3);
    bool flag =  (*p)->Init(host, port);

    lua_pushinteger(L, flag);

    return 1;
}

static int lua_get_record(lua_State* L)
{
    CMemcacheClient** p = (CMemcacheClient**)luaL_checkudata(L, 1, "libmemcahed_client");
    luaL_argcheck(L, p != NULL, 1, "invalid user data");

    const char* k = luaL_checkstring(L, -1);
    std::string v =  (*p)->GetRecord(k);

    lua_pushstring(L, v.c_str());

    return 1;
}

static int lua_set_record(lua_State* L)
{
    CMemcacheClient** p = (CMemcacheClient**)luaL_checkudata(L, 1, "libmemcahed_client");
    luaL_argcheck(L, p != NULL, 1, "invalid user data");

    const char* uid = luaL_checkstring(L, 2);
    const char* value = luaL_checkstring(L, 3);
    unsigned int len = luaL_checkinteger(L, 4);

    int ret = (*p)->SetRecord(uid, value, len);

    lua_pushinteger(L, ret);

    return 1;
}


static int lua_delete_base(lua_State* L)
{
    CMemcacheClient** p = (CMemcacheClient**)luaL_checkudata(L, 1, "libmemcahed_client");
    luaL_argcheck(L, p != NULL, 1, "invalid user data");
    
    if (p) {
        //std::cout<<"lua_delete_base!"<<endl;
        delete *p;
    }

    return 1;
}

static const luaL_Reg registerInfo[] = {
    {"__gc", lua_delete_base},
   
    {"create_libmemcahed_client", lua_create_libmemcahed_client},
    {"init_libmemcahed_client", lua_init_libmemcahed_client},
    {"get_record", lua_get_record},
    {"set_record", lua_set_record},

    {NULL, NULL}
};


extern "C" _DLLExport int luaopen_lua_memcached(lua_State *L)
{
    luaL_newmetatable(L, "libmemcahed_client");
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");

	luaL_setfuncs(L, registerInfo, 0);

    return 1;
}
